
/** Clones a sequence (vector or object) adding a reference
	to each sub-item in an object. */
Val* seq_clone(VM* vm, Val* xs) {
	Val* r = val_new(xs->type);
	r->data.ObjectData.adata = array_clone(xs->data.ObjectData.adata);
	if (xs->type == ObjectType) {
		// We add reference to children only if the cloning an object
		int i = 0;
		int n = obj_count(xs);
		for (; i < n; ++i)
			val_add_ref(obj_at(xs, i));
	}
	return r;
}

/** Returns the nth item of a sequence. */
Val* seq_get(VM* vm, int n, Val* xs) {
	if (val_is_vec(xs)) 
		return vec_get_val(xs, n);
	else if (val_is_obj(xs)) 
		return val_add_ref(obj_at(xs, n));	
	TYPE_ERROR();
	return NULL;
}

/** Sets the nth item of a sequence. */
void seq_set(VM* vm, int n, Val* x, Val* xs) {
	if (val_is_vec(xs)) 
		vec_set_val(xs, x, n);
	else if (val_is_obj(xs)) 
		obj_at(xs, n) = x;
	else
		TYPE_ERROR();
}

/** Concatenates two sequences. */
Val* seq_cat_impl(VM* vm, Val* v0, Val* v1) {
	int n0 = obj_count(v0);
	int n1 = obj_count(v1);
	Val* r = vec_new(v0->type, n0 + n1);
	assert(v0->type == v1->type);
	memcpy(obj_begin(r), obj_begin(v0), vec_num_bytes(v0));
	memcpy(obj_begin(r) + n0, obj_begin(v1), vec_num_bytes(v1));
	val_del_ref(v0);
	val_del_ref(v1);
	return r;
}

